自治事务
自治事务的创建
自治事务是由另一个事务(主事务)启动的独立事务,它在执行SQL操作并提交或回滚,而无需提交或回滚主事务。并且其还具有如下特点:
自治事务不与主事务共享事务资源(如锁)。
自治事务不依赖于主事务。例如,如果主事务回滚,则嵌套事务会回滚,但自治事务不会回滚。
自治事务提交的更改会立即对其他事务可见。
自治事务的异常部分属于外部事务,自治事务中引发的异常会导致事务级回滚,而非语句级回滚。
语法
自治事务的使用
-
ORACLE模式下运行。
-
声明部分将例程标记为自治事务。
-
应用场景包括:存储过程、函数、包、触发器。
-
不支持重复声明自治事务。
-
不支持在嵌套块内声明自治事务。
-
当进入自治例程的可执行部分时,主事务暂停。回退自治例程后,主事务将恢复。
-
COMMIT并结束活动的自治事务,但例程未执行结束。
-
保存点的作用域是在其中定义它的事务。事实上,主事务和自治事务可以使用相同的保存点名称。
-
自治例程依然属于当前会话,如时间格式、序列等以会话粒度使用的功能。自治例程与外部保持一致。
-
会话级隔离级别设置,自治事务设置后影响外部主事务事务属性,与其共享。
-
事务级隔离级别或属性设置,自治事务设置仅影响本事务,不影响外部主事务。亦或是自治例程内commit后由下一个语句开启的新事务,同样不受影响。
示例
create table employees(employee_id varchar(64),amount int,salary int);
insert into employees values(100,100,1000);
set environment sqlmode 'oracle';
创建plsql匿名块
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
emp_id NUMBER(6) := 100;
amount NUMBER(6,2) := 200;
BEGIN
UPDATE employees SET salary = salary - amount
WHERE employee_id = emp_id;
COMMIT;
END;
/
创建存储过程
CREATE OR REPLACE PROCEDURE lower_salary
(emp_id NUMBER, amount NUMBER)
AUTHID DEFINER AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE employees
SET salary = salary - amount
WHERE employee_id = emp_id;
COMMIT;
END lower_salary;
/
创建包
CREATE OR REPLACE PACKAGE emp_actions AUTHID DEFINER AS
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)
RETURN NUMBER;
END emp_actions;
/
CREATE OR REPLACE PACKAGE BODY emp_actions AS
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)
RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION;
new_sal NUMBER(8,2);
BEGIN
UPDATE employees SET salary =
salary + sal_raise WHERE employee_id = emp_id;
COMMIT;
SELECT salary INTO new_sal FROM employees
WHERE employee_id = emp_id;
RETURN new_sal;
END raise_salary;
END emp_actions;
/
创建触发器
CREATE TABLE log(
log_id NUMBER(6),up_date DATE,new_sal NUMBER(8,2),old_sal NUMBER(8,2));
CREATE TABLE emp(empno varchar(32),sal int);
CREATE OR REPLACE TRIGGER log_sal
BEFORE UPDATE OF sal ON emp FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO log (
log_id,
up_date,
new_sal,
old_sal
)
VALUES (
:old.empno,
SYSDATE,
:new.sal,
:old.sal
);
--COMMIT;
END;
/